home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1999 May: Tool Chest / Developer CD Series Tool Chest (Apple Computer)(May 1999).iso / Tool Chest / Devices / CD-ROM / iso9660 / Srcs / TextDlog.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-09-28  |  9.6 KB  |  367 lines  |  [TEXT/MPS ]

  1. /*
  2.     Present a dialog box with a text rectangle, a scroll bar, and an OK
  3.     button.  This can be used as a help dialog.  Pass in a dialog
  4.     resource number and a handle to the text.  The dialog should
  5.     have the OK button as the first item, and user items for the
  6.     second and third items.  The second is the rect in which the
  7.     control is drawn, the third is the rect in which text is drawn.
  8.     Only the OK button should be enabled.
  9.  
  10.     The text handle should be locked before calling TextDlog and
  11.     unlocked after.
  12.  
  13.     Original author:                     dubois@uwmacc.UUCP (Paul DuBois)
  14.     with a few changes & cleanup by:     blob@apple.com    (Brian Bechtel)
  15. */
  16.  
  17. #include <stdio.h>
  18. # include    <Events.h>
  19. # include    <Dialogs.h>
  20. # include    <Controls.h>
  21.  
  22. #include "textdlog.h"
  23. #include "DialogUtils.h"
  24.  
  25. #define    ETX    03        /* Enter key */
  26. #define CR    13        /* Return key */
  27.  
  28. #include "TextDlog.proto.h"
  29.  
  30. enum        /* item numbers */
  31. {
  32.     OKButton = 1,
  33.     scrollBarUser,
  34.     textRectUser
  35. };
  36.  
  37. static ControlHandle    theScroll;
  38. static Boolean            needScroll;    /* true if need scroll bar */
  39. static short                curLine;
  40. static short                halfPage;
  41. static TEHandle            teHand;
  42.  
  43.  
  44.  
  45. /************************************************************************
  46.  *
  47.  *  Function:        HighLightDefault
  48.  *
  49.  *  Purpose:        highlight the default button in a dialog
  50.  *
  51.  *  Returns:        nothing
  52.  *
  53.  *  Side Effects:    standard box is drawn around highlight box
  54.  *
  55.  *  Description:    draws the heavy rounded box around the OK button,
  56.  *                    so that the user knows that hitting enter or return
  57.  *                    is the same as pressing the OK button.
  58.  *
  59.  ************************************************************************/
  60. void
  61. HighLightDefault(DialogPtr dPtr)
  62. {
  63.     short unusedItemType;
  64.     Handle unusedItemHandle;
  65.     Rect box;
  66.     PenState p;
  67.     GrafPtr    savedPort;
  68.  
  69.     /*    This next little piece of code puts the default heavy rounded
  70.         box around the "OK" button, so the user knows that pressing
  71.         return is the same as hitting "OK"
  72.     */
  73.     GetPort(&savedPort);
  74.     SetPort(dPtr);        /* without this, can't highlite OK */
  75.     GetDItem(dPtr, OKButton, &unusedItemType, &unusedItemHandle, &box);
  76.     GetPenState(&p);
  77.     PenSize(3,3);
  78.     InsetRect(&box, -4, -4);
  79.     FrameRoundRect(&box, 16, 16);
  80.     PenSize(p.pnSize.h, p.pnSize.v);
  81.     SetPort(savedPort);
  82. }
  83.  
  84. /************************************************************************
  85.  *
  86.  *  Function:        DrawScroll
  87.  *
  88.  *  Purpose:        draw scroll bar user item
  89.  *
  90.  *  Returns:        nothing
  91.  *
  92.  *  Side Effects:    draws scroll bar user item
  93.  *
  94.  *  Description:    if we need to scroll, show the control.
  95.  *
  96.  ************************************************************************/
  97. static pascal void DrawScroll (DialogPtr theDialog, short itemNo)
  98. {
  99.     if (needScroll)
  100.         ShowControl (theScroll);
  101. }
  102.  
  103.  
  104. /************************************************************************
  105.  *
  106.  *  Function:        DrawTextRect
  107.  *
  108.  *  Purpose:        draw text display user item
  109.  *
  110.  *  Returns:        nothing
  111.  *
  112.  *  Side Effects:    shows the text
  113.  *
  114.  *  Description:    Get the rectangle for our text.  If we need to scroll,
  115.  *                    frame the rectangle so that it will look correct.
  116.  *                    Get the view rectangle of our text rectangle, and do
  117.  *                    a TEUpdate so that text edit will properly handle
  118.  *                    updating the rectangle.
  119.  *
  120.  ************************************************************************/
  121. static pascal void DrawTextRect (DialogPtr theDialog, short itemNo)
  122. {
  123. Rect    r;
  124. short        itemType;
  125. Handle    itemHandle;
  126.  
  127.     GetDItem (theDialog, textRectUser, &itemType, &itemHandle, &r);
  128.     if (needScroll)
  129.         FrameRect (&r);
  130.     r = (**teHand).viewRect;
  131.     TEUpdate (&r, teHand);
  132. }
  133.  
  134.  
  135. /************************************************************************
  136.  *
  137.  *  Function:        DoScroll
  138.  *
  139.  *  Purpose:        scroll to correct position
  140.  *
  141.  *  Returns:        nothing.
  142.  *
  143.  *  Side Effects:    text is scrolled to new position
  144.  *
  145.  *  Description:
  146.  *                    Scroll to the correct position.  lDelta is the
  147.  *                    amount to CHANGE the current scroll setting by.
  148.  *
  149.  ************************************************************************/
  150. static void
  151. DoScroll (short lDelta)
  152. {
  153. short    newLine;
  154.  
  155.     newLine = curLine + lDelta;
  156.     if (newLine < 0) newLine = 0;
  157.     if (newLine > GetCtlMax (theScroll)) newLine = GetCtlMax (theScroll);
  158.     SetCtlValue (theScroll, newLine);
  159.     lDelta = (curLine - newLine ) * (**teHand).lineHeight;
  160.     TEScroll (0, lDelta, teHand);
  161.     curLine = newLine;
  162. }
  163.  
  164.  
  165.  
  166. /************************************************************************
  167.  *
  168.  *  Function:        
  169.  *
  170.  *  Purpose:        track the scrolling
  171.  *
  172.  *  Returns:        nothing
  173.  *
  174.  *  Side Effects:    scrolling
  175.  *
  176.  *  Description:    get the control part that we're in.  If we're still
  177.  *                    in the same part, we're going to scroll.  Check what
  178.  *                    kind of part we're in, and set our delta accordingly.
  179.  *                    Call DoScroll to actually handle the scrolling.
  180.  *
  181.  ************************************************************************/
  182. static pascal void __TrackScroll (ControlHandle theScroll, short partCode)
  183. {
  184. short    lDelta;
  185.  
  186.     if (partCode == GetCRefCon (theScroll))    /* still in same part? */
  187.     {
  188.         switch (partCode)
  189.         {
  190.             case inUpButton: lDelta = -1; break;
  191.             case inDownButton: lDelta = 1; break;
  192.             case inPageUp: lDelta = -halfPage; break;
  193.             case inPageDown: lDelta = halfPage; break;
  194.         }
  195.         DoScroll (lDelta);
  196.     }
  197. }
  198.  
  199.  
  200. /************************************************************************
  201.  *
  202.  *  Function:        TextFilter
  203.  *
  204.  *  Purpose:        filter to handle hits in scroll bar
  205.  *
  206.  *  Returns:        false (indicating we should continue within our
  207.  *                    modal dialog)
  208.  *
  209.  *  Side Effects:    May scroll the text
  210.  *
  211.  *  Description:    We're being called as part of a ModalDialog call.
  212.  *                    Check what kind of event activated us.  If it was a
  213.  *                    mouseDown, handle it.  If we were in the thumb, track
  214.  *                    the thumb, otherwise scroll the indicated amount.
  215.  *
  216.  ************************************************************************/
  217. static pascal Boolean TextFilter (DialogPtr theDialog, EventRecord *theEvent, short *itemHit)
  218. {
  219. Point    thePoint;
  220. short        thePart;
  221. Boolean    result;
  222. static ControlActionUPP    gTrack;
  223.  
  224.     gTrack = NewControlActionProc(__TrackScroll);
  225.     result = false;
  226.     switch (theEvent->what)
  227.     {
  228.         case mouseDown:
  229.             thePoint = theEvent->where;
  230.             GlobalToLocal (&thePoint);
  231.             thePart = TestControl (theScroll, thePoint);
  232.             if (thePart == inThumb)
  233.             {
  234.                 (void) TrackControl (theScroll, thePoint, nil);
  235.                 DoScroll (GetCtlValue (theScroll) - curLine);
  236.             }
  237.             else if (thePart != 0)
  238.             {
  239.                 SetCRefCon (theScroll, (long) thePart);
  240.                 (void) TrackControl (theScroll, thePoint, gTrack);
  241.             }
  242.             break;
  243.         case keyDown:
  244.             if ((theEvent->message & charCodeMask) == ETX)
  245.             {
  246.                 *itemHit = 1;
  247.                 result = true;
  248.             }
  249.             if ((theEvent->message & charCodeMask) == CR)
  250.             {
  251.                 *itemHit = 1;
  252.                 result = true;
  253.             }
  254.             break;
  255.         case updateEvt:
  256.         case activateEvt:
  257.             HighLightDefault(theDialog);
  258.             break;
  259.     }
  260.     DisposeRoutineDescriptor(gTrack);
  261.     return (result);
  262. }
  263.  
  264.  
  265.  
  266. /************************************************************************
  267.  *
  268.  *  Function:        TextDialog
  269.  *
  270.  *  Purpose:        put up text dialog with optional scroll bar
  271.  *
  272.  *  Returns:        nothing
  273.  *
  274.  *  Side Effects:    none
  275.  *
  276.  *  Description:    Pass in a dialog number, a handle to the text to
  277.  *                    display, a font number, font size, and a boolean
  278.  *                    indicating whether you want the text to wrap or not.
  279.  *
  280.  *                    The dialog referenced by dlogNum should have the 
  281.  *                    OK button as the first item, and user items for the
  282.  *                    second and third items.  The second is the rect in
  283.  *                    which the control is drawn, the third is the rect in
  284.  *                    which text is drawn. Only the OK button should be
  285.  *                    enabled.
  286.  *
  287.  *                    The text handle should be locked before calling us,
  288.  *                    and unlocked afterwards.
  289.  *
  290.  *                    Of course, the font number and size should exist in
  291.  *                    the current system, or it will default to something
  292.  *                    ugly.
  293.  *
  294.  ************************************************************************/
  295. void
  296. TextDialog (short dlogNum, Handle textHandle, short fontNum, short fontSize, Boolean wrap)
  297. {
  298. GrafPtr        oldPort;
  299. DialogPtr    theDialog;
  300. short            itemNo;
  301. short        itemType;
  302. Handle        itemHandle;
  303. Rect        r;
  304. short            scrollLines;
  305. short            viewLines;
  306. Handle        oldHText;
  307. static ModalFilterUPP        filterProc;
  308. static UserItemUPP            drawTextProc;
  309. static UserItemUPP            drawScrollProc;
  310.  
  311.     GetPort (&oldPort);
  312.     theDialog = GetNewDialog (DU_CenterDLOG(dlogNum), (DialogPeek)nil, (WindowPtr)-1L);
  313.  
  314.     GetDItem (theDialog, textRectUser, &itemType, &itemHandle, &r);
  315.     drawTextProc = NewUserItemProc(DrawTextRect);
  316.     SetDItem (theDialog, textRectUser, itemType, (Handle)drawTextProc, &r);
  317. /*
  318.     incorporate text into a TERec.
  319. */
  320.     SetPort (theDialog);
  321.     TextFont (fontNum);
  322.     TextSize (fontSize);
  323.  
  324.     InsetRect (&r, 4, 4);
  325.     teHand = TENew (&r, &r);
  326.     if (!wrap)
  327.         (**teHand).crOnly = -1;
  328.     oldHText = (**teHand).hText;        /* save this.  restore later */
  329.     (**teHand).hText = textHandle;
  330.     TECalText (teHand);
  331.     viewLines = (r.bottom - r.top) / (**teHand).lineHeight;
  332.     scrollLines = (**teHand).nLines - viewLines;
  333.     needScroll = (scrollLines > 0);
  334.     GetDItem (theDialog, scrollBarUser, &itemType, &itemHandle, &r);
  335.     drawScrollProc = NewUserItemProc(DrawScroll);
  336.     SetDItem (theDialog, scrollBarUser, itemType, (Handle)drawScrollProc, &r);
  337.     if (needScroll)
  338.     {
  339.         theScroll = NewControl (theDialog, &r, NULL, false, 0, 0, 0,
  340.                         scrollBarProc, 0L);
  341.         SetCtlMax (theScroll, scrollLines);
  342.         halfPage = viewLines / 2;
  343.         curLine = 0;
  344.         filterProc = NewModalFilterProc(TextFilter);
  345.     }
  346.  
  347.     ShowWindow (theDialog);
  348.  
  349.     do {
  350.         ModalDialog (filterProc, &itemNo);
  351.     } while (itemNo != OKButton);
  352.  
  353. /*
  354.     restore hText field of TE record before disposing of it.
  355. */
  356.     (**teHand).hText = oldHText;
  357.     TEDispose (teHand);
  358.  
  359.     if (needScroll)
  360.         DisposeControl (theScroll);
  361.     SetPort (oldPort);
  362.     DisposeRoutineDescriptor(filterProc);
  363.     DisposeRoutineDescriptor(drawScrollProc);
  364.     DisposeRoutineDescriptor(drawTextProc);
  365.     DisposDialog(theDialog);
  366. }
  367.